﻿using System;
using System.IO;
using System.Linq;
using System.Security.Claims;
using System.Security.Policy;
using System.Threading.Tasks;
using CMS.Admin.Services;
using CMS.Model;
using CMS.ViewModels;
using CMS.Web;
using CMS.Web.Controllers.Admin;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.Logging;

namespace CMS.Admin.Controllers.Admin
{
    [Authorize]
    [Route("admin/[controller]/[action]")]
    public class AccountController : AdminBaseController
    {
        private readonly SignInManager<User> _signInManager;
        private readonly IEmailSender _emailSender;
        private readonly ISmsSender _smsSender;
        private readonly ILogger _logger;
        protected readonly IWebHostEnvironment _env;

        public AccountController(
            UserManager<User> userManager,
            SignInManager<User> signInManager,
            IEmailSender emailSender,
            ISmsSender smsSender,
            ILoggerFactory loggerFactory, IWebHostEnvironment env) : base(userManager)
        {
            _signInManager = signInManager;
            _emailSender = emailSender;
            _smsSender = smsSender;
            _logger = loggerFactory.CreateLogger<AccountController>();
            _env = env;
        }

        //
        // GET: /Account/Login
        [HttpGet]
        [AllowAnonymous]
        public IActionResult Login()
        {
            return View();
        }

        //
        // POST: /Account/Login
        [HttpPost]
        [AllowAnonymous]
        public async Task<IActionResult> Login([FromBody] LoginViewModel model, string returnUrl = null)
        {
            // This doesn't count login failures towards account lockout
            // To enable password failures to trigger account lockout, set lockoutOnFailure: true
            var result = await _signInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, lockoutOnFailure: false);
            if (result.Succeeded)
            {
                var user = await _userManager.FindByNameAsync(model.UserName);
                jsonResponse.Set(ARTag.success);
                jsonResponse.data = new { name = user.UserName, avatar = "/img/user.jpg" };
                jsonResponse.msg = "登录成功";
            }
            else
            {
                jsonResponse.Set(ARTag.invalid);
                jsonResponse.msg = "用户名密码错误";
            }
            return Json(jsonResponse);
        }

        //
        // GET: /Account/Register
        [HttpGet]
        [AllowAnonymous]
        public IActionResult Register(string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            return NotFound();
            //return View();
        }

        //
        // POST: /Account/Register
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            if (ModelState.IsValid)
            {
                var user = new User { UserName = model.UserName, Email = model.Email, Deleted = 0, Id = Guid.NewGuid().ToString(), CreateTime = DateTime.Now, Usertype = 0 };
                var result = await _userManager.CreateAsync(user, model.Password);
                if (result.Succeeded)
                {
                    await _signInManager.SignInAsync(user, isPersistent: false);
                    _logger.LogInformation(3, "User created a new account with password.");
                    return RedirectToLocal(returnUrl);
                }
                AddErrors(result);
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        //
        // POST: /Account/LogOff
        [HttpPost]
        [AllowAnonymous]
        public async Task<IActionResult> LogOff()
        {
            await _signInManager.SignOutAsync();
            _logger.LogInformation(4, "User logged out.");
            jsonResponse.Set(ARTag.success);
            return Json(jsonResponse);
        }

        [HttpPost]
        [Authorize]
        public async Task<IActionResult> Profile([FromBody] Profile profile)
        {
            try
            {
                var user = await _userManager.FindByNameAsync(profile.UserName);
                if (user != null)
                {
                    if (profile.Avatar.Length > 0)
                    {
                        var filename = Path.Combine(_env.WebRootPath, "UserAvatar", user.Id, $"{ Guid.NewGuid().ToString()}.{profile.Avatar.Split(",")[0].Split(";")[0].Split("/")[1]}");
                        string path = Path.Combine(_env.WebRootPath, "UserAvatar", user.Id);
                        if (!Directory.Exists(path))
                        {
                            Directory.CreateDirectory(path);
                        }
                        using (var stream = new FileStream(filename, FileMode.Create, FileAccess.Write))
                        {
                            byte[] avatarByte = Convert.FromBase64String(profile.Avatar.Split(",")[1]);
                            await stream.WriteAsync(avatarByte);
                        }
                        user.Avatar = Path.GetFileName(filename);
                        var ret = await _userManager.UpdateAsync(user);
                        if (ret.Succeeded)
                        {
                            jsonResponse.Set(ARTag.success);
                            jsonResponse.data = new { name = user.UserName, avatar = "/img/user.jpg" };
                        }
                    }
                }
                if (!string.IsNullOrEmpty(profile.NewPassword))
                {
                    var sign = await _signInManager.PasswordSignInAsync(user.UserName, profile.Password, false, lockoutOnFailure: false);
                    if (sign.Succeeded)
                    {
                        var token = await _userManager.GeneratePasswordResetTokenAsync(user);
                        var ret = await _userManager.ResetPasswordAsync(user, token, profile.NewPassword);
                        if (ret.Succeeded)
                        {
                            await _signInManager.SignOutAsync();
                            jsonResponse.Set(ARTag.success);
                        }
                        else
                        {
                            jsonResponse.Set(ARTag.error);
                            jsonResponse.msg = "密码长度最少为6位！";
                        }
                    }
                    else
                    {
                        jsonResponse.Set(ARTag.error);
                        jsonResponse.msg = "原密码不正确！";
                    }
                }
                return Json(jsonResponse);
            }
            catch (Exception ex)
            {
                jsonResponse.Set(ARTag.error);
                jsonResponse.msg = ex.Message;
                return Json(jsonResponse);
            }
        }


        [HttpGet]
        [AllowAnonymous]
        public async Task<IActionResult> ConfirmEmail(string userId, string code)
        {
            if (userId == null || code == null)
            {
                return View("Error");
            }
            var user = await _userManager.FindByIdAsync(userId);
            if (user == null)
            {
                return View("Error");
            }
            var result = await _userManager.ConfirmEmailAsync(user, code);
            return View(result.Succeeded ? "ConfirmEmail" : "Error");
        }

        [HttpGet]
        [AllowAnonymous]
        public IActionResult ForgotPasswordConfirmation()
        {
            return View();
        }

        //
        // GET: /Account/ResetPassword
        [HttpGet]
        [AllowAnonymous]
        public IActionResult ResetPassword(string code = null)
        {
            return code == null ? View("Error") : View();
        }



        //
        // GET: /Account/ResetPasswordConfirmation
        [HttpGet]
        [AllowAnonymous]
        public IActionResult ResetPasswordConfirmation()
        {
            return View();
        }



        #region Helpers

        private void AddErrors(IdentityResult result)
        {
            foreach (var error in result.Errors)
            {
                ModelState.AddModelError(string.Empty, error.Description);
            }
        }

        private Task<User> GetCurrentUserAsync()
        {
            return _userManager.GetUserAsync(HttpContext.User);
        }

        private IActionResult RedirectToLocal(string returnUrl)
        {
            if (Url.IsLocalUrl(returnUrl))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return RedirectToAction(nameof(AdminController.Index), "Home");
            }
        }

        #endregion
    }
}
